package com.ruoyi.framework.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.CryptoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Component
public class DecryptionFilter extends OncePerRequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(DecryptionFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 如果是文件上传请求，直接跳过解密
        if (isFileUploadRequest(request)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 创建请求包装器处理解密
        DecryptionRequestWrapper requestWrapper = new DecryptionRequestWrapper(request);
        filterChain.doFilter(requestWrapper, response);
    }

    // 判断是否是文件上传请求
    private boolean isFileUploadRequest(HttpServletRequest request) {
        return request.getContentType() != null && request.getContentType().contains("multipart/form-data");
    }

    // 请求包装类
    private class DecryptionRequestWrapper extends HttpServletRequestWrapper {
        private Map<String, String[]> parameterMap;
        private byte[] body = new byte[0]; // 初始化为空数组，避免NPE
        private final ObjectMapper objectMapper = new ObjectMapper();

        public DecryptionRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);

            // 处理GET请求参数解密
            if ("GET".equalsIgnoreCase(request.getMethod())) {
                processParameters(request);
            }
            // 处理POST请求体解密
            else {
                try {
                    // 读取请求体内容
                    StringBuilder stringBuilder = new StringBuilder();
                    String line;
                    try (BufferedReader bufferedReader = request.getReader()) {
                        while ((line = bufferedReader.readLine()) != null) {
                            stringBuilder.append(line);
                        }
                    }
                    String requestBody = stringBuilder.toString();

                    // 设置默认请求体
                    if (!requestBody.isEmpty()) {
                        body = requestBody.getBytes(StandardCharsets.UTF_8);

                        // 仅处理JSON内容类型
                        if (request.getContentType() != null && request.getContentType().contains("application/json")) {
                            processJsonBody(requestBody);
                        }
                    }
                } catch (Exception e) {
                    logger.error("读取请求体失败", e);
                    // 保留空请求体
                }
            }
        }

        private void processParameters(HttpServletRequest request) {
            parameterMap = new HashMap<>(request.getParameterMap());
            String encrypted = request.getParameter("encrypted");

            if (encrypted != null && !encrypted.isEmpty()) {
                try {
                    String decrypted = CryptoUtils.decrypt(encrypted);
                    // 解析解密后的查询字符串为参数
                    parseQueryString(decrypted);
                    // 移除加密参数
                    parameterMap.remove("encrypted");
                } catch (Exception e) {
                    logger.error("Failed to decrypt request parameters", e);
                }
            }
        }

        private void parseQueryString(String queryString) {
            String[] pairs = queryString.split("&");
            for (String pair : pairs) {
                int idx = pair.indexOf("=");
                String key = idx > 0 ? pair.substring(0, idx) : pair;
                String value = idx > 0 && pair.length() > idx + 1 ? pair.substring(idx + 1) : "";

                // 添加到参数map
                String[] values = parameterMap.get(key);
                if (values == null) {
                    parameterMap.put(key, new String[]{value});
                } else {
                    String[] newValues = new String[values.length + 1];
                    System.arraycopy(values, 0, newValues, 0, values.length);
                    newValues[values.length] = value;
                    parameterMap.put(key, newValues);
                }
            }
        }

        private void processJsonBody(String requestBody) {
            try {
                // 解析JSON
                Map<String, Object> requestMap = objectMapper.readValue(requestBody, Map.class);
                String encrypted = (String) requestMap.get("encrypted");

                if (encrypted != null) {
                    try {
                        // 尝试解密
                        String decrypted = CryptoUtils.decrypt(encrypted);
                        System.out.println("【调试】解密请求体: " + encrypted);

                        // 解密成功后，将解密结果当作新的请求体
                        body = decrypted.getBytes(StandardCharsets.UTF_8);
                    } catch (Exception e) {
                        logger.error("解密失败，继续使用原始请求体", e);
                    }
                }
            } catch (Exception e) {
                logger.error("处理请求体失败", e);
            }
        }

        @Override
        public String getParameter(String name) {
            String[] values = getParameterValues(name);
            return values != null && values.length > 0 ? values[0] : null;
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return parameterMap != null ? parameterMap : super.getParameterMap();
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return java.util.Collections.enumeration(getParameterMap().keySet());
        }

        @Override
        public String[] getParameterValues(String name) {
            return getParameterMap().get(name);
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }

        @Override
        public javax.servlet.ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);

            return new javax.servlet.ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }

                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return true;
                }

                @Override
                public void setReadListener(javax.servlet.ReadListener readListener) {
                    // Not implemented
                }
            };
        }
    }
}
